﻿using Bettzueche.RLLibrary.Types;
using System.Text;
using System.Windows;

namespace RLProject1.Model.AMEEWorld
{
    /// <summary>
    /// Aktion: Gehe in Abschnitt (Spur,Ring) = Position (x,y) bezogen auf das egozentrische WorldImage.
    /// </summary>
    /// <remarks>Implizite Konvertierung nach Int32 (= Abschnittsnummer) und <see cref="System.Windows.Vector">Vector</see> (= (X,Y)) unterstützt.<para>
    /// Die von <see cref="Bettzueche.RLLibrary.Types.IActionID">IActionID</see> geerbte Eigenschaft <c>ID</c> ist identisch
    /// zum Feld <c>Abschnittsnummer</c>.</para><para>
    /// Die X,Y Koordinate bezieht sich (normalerweise) auf das Zentrum von <see cref="WorldImage">WorldImage</see></para></remarks>
    public struct AMEEAction : IActionID
    {
        /// <summary>
        /// Die Abschnittsnummer.<para>
        /// Normalerweise eindeutig und ergibt sich bspw. aus Spurnummer * 'SektorenGesamt' + SektorNummer</para>
        /// </summary>
        public int Abschnittsnummer;

        /// <summary>Die Sektornummer</summary>
        public int SektorNummer;

        /// <summary>Die Spurnummer</summary>
        public int SpurNummer;

        /// <summary>X-Koordinate des Abschnittmittelpunktes im egozentrischen WorldImage</summary>
        public double X;

        /// <summary>Y-Koordinate des Abschnittmittelpunktes im egozentrischen WorldImage</summary>
        public double Y;

        /// <summary>
        /// Returns a hash code for this instance.
        /// </summary>
        /// <returns>
        /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. 
        /// </returns>
        public override int GetHashCode() {
            int hash = 1;
            hash = hash * 11 + SektorNummer;
            hash = hash * 31 + SpurNummer;
            hash = hash * 17 + X.GetHashCode();
            hash = hash * 5 + Y.GetHashCode();
            return hash;
        }

        /// <summary>
        /// Determines whether the specified <see cref="System.Object" /> is equal to this instance.
        /// </summary>
        /// <param name="obj">The <see cref="System.Object" /> to compare with this instance.</param>
        /// <returns>
        ///   <c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.
        /// </returns>
        public override bool Equals(object obj) {
            if (!(obj is AMEEAction))
                return false;
            AMEEAction other = (AMEEAction)obj;
            if (other.Abschnittsnummer != this.Abschnittsnummer)
                return false;
            if (!(other.SektorNummer == this.SektorNummer && other.SpurNummer == this.SpurNummer))
                return false;
            if (!(other.X == this.X && other.Y == this.Y))
                return false;
            return true; 
        }

        /// <summary>
        /// Returns a <see cref="System.String" /> that represents this instance.
        /// </summary>
        /// <returns>
        /// A <see cref="System.String" /> that represents this instance.
        /// </returns>
        public override string ToString() {
            StringBuilder str = new StringBuilder("AMEEAktion_");
            str.Append(Abschnittsnummer);
            str.Append("(Sp ").Append(SpurNummer).Append(",Se ").Append(SektorNummer).Append(")");
            str.Append("(").Append(X.ToString("F3")).Append(",").Append(Y.ToString("F3")).Append(")");
            return str.ToString();
        }

        /// <summary>
        /// Konvertiert implizit eine AMEEAction nach Int32.
        /// </summary>
        /// <param name="action">The action.</param>
        /// <returns>action.Abschnittsnummer</returns>
        public static implicit operator int(AMEEAction action) {
            return action.Abschnittsnummer;
        }

        /// <summary>
        /// Konvertiert implizit eine AMEEAction nach <see cref="System.Windows.Vector"/>.
        /// </summary>
        /// <param name="action">The action.</param>
        /// <returns><see cref="System.Windows.Vector"/> v mit v.X = action.X und v.Y = action.Y</returns>
        public static implicit operator Vector(AMEEAction action) {
            return new Vector { X = action.X, Y = action.Y };
        }

        /// <summary>
        /// Gibt oder setzt das Feld <c>Abschnittsnummer</c>
        /// </summary>
        /// <value>
        /// Die Abschnittsnummer.<para>
        /// Normalerweise eindeutig und ergibt sich bspw. aus Spurnummer * 'SektorenGesamt' + SektorNummer</para>
        /// </value>
        public int ID {
            get { return this.Abschnittsnummer; }
            set { Abschnittsnummer = value; }
        }
    }
}
